package com.ala4.oxcafe.common.utils;

import com.ala4.oxcafe.common.utils.text.StrUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Redis工具类
 *
 * @author PING
 * @date 2022/9/15 11:25
 */
@Slf4j
@Component
public class RedisUtil {

    private static RedisTemplate<String, String> redisTemplate;

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     */
    public static void expire(String key, long time) {
        if (time > 0) {
            redisTemplate.expire(key, time, TimeUnit.SECONDS);
        }
    }

    // =============================common============================

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public static long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public static boolean hasKey(String key) {
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public static void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(Arrays.stream(key).collect(Collectors.toList()));
            }
        }
    }

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public static <T> T get(String key, Class<T> tClass) {
        if (StrUtil.isEmpty(key)) {
            return null;
        }
        String jsonStr = redisTemplate.opsForValue().get(key);
        if (StrUtil.isEmpty(jsonStr)) {
            return null;
        }
        //如果是字符串 不需要去除引号
        if (tClass == String.class) {
            return JSONUtil.toBean(jsonStr, new TypeReference<T>() {
            });
        }
        if (tClass == Long.class || tClass == Integer.class || tClass == Double.class || tClass == Float.class) {
            //log.info("基础数据类型强制转换:{}-{}", tClass, jsonStr);
            // 基础数据类型 存的时候都是tojsonstr了
            // 现在重新拿出来的时候需要去掉引号
            jsonStr = jsonStr.replace("\"", "");
            return JSONUtil.toBean(jsonStr, new TypeReference<T>() {
            });
        }
        //log.info("toBean:{}-{}", tClass, jsonStr);
        return JSONUtil.toBean(jsonStr, tClass);
    }

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public static <T> T get(String key, TypeReference<T> typeReference) {
        if (StrUtil.isEmpty(key)) {
            return null;
        }
        String jsonStr = redisTemplate.opsForValue().get(key);
        if (StrUtil.isEmpty(jsonStr)) {
            return null;
        }
        return JSONUtil.toBean(jsonStr, typeReference);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public static void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value));
    }

    /**
     * 添加list
     *
     * @param key
     * @param value
     * @param time
     */
    public static void list(String key, Object value, Long time) {
        redisTemplate.opsForList().leftPush(key, JSONUtil.toJsonStr(value));
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public static void set(String key, Object value, long time) {
        if (time > 0) {
            redisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, TimeUnit.SECONDS);
        } else {
            set(key, value);
        }
    }

    public static Long incr(String key) {
        return redisTemplate.opsForValue().increment(key, 1);
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
        RedisUtil.redisTemplate = redisTemplate;
    }

}
